package im.agents.monitor;

import java.util.Calendar;
import java.util.Random;

import jade.core.Agent;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.FIPANames;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import im.agents.INodeMonitor;
import im.agents.utility.Utility;
import im.domain.*;


public class RefreshMonitorData extends TickerBehaviour {

	public static int SUCCESS_RATE = 30;
	private Context context;
	private int max = 1500; // estremo superiore di partenza
	
	
	public RefreshMonitorData(Agent a, long period) {
		super(a, period);
		setContext();
	}

	private void setContext() {
		
		DFAgentDescription context_ds = Utility.findAgent(myAgent,"context-info");
		String convId = Utility.createConvId(myAgent);
		ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
		request.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
		request.setSender(myAgent.getAID());
		request.addReceiver(context_ds.getName());
		request.setConversationId(convId);
		myAgent.send(request);

		boolean gotIt=false;
		while(!gotIt){
			ACLMessage response = myAgent.receive(
			MessageTemplate.MatchConversationId(convId));
			if(response!=null){
				context = (Context) XMLSerializer.doDeserialize(response.getContent());
			    gotIt = true;
			}
			else{
				block();
			}
		}
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTick() {
		
		//System.out.println("Ciao sono un monitor,mi chiamo"+myAgent.getName()+"e mi aggiorno");
		
		//System.out.println("refresh - tick");
		Random random = new Random(Calendar.getInstance().getTimeInMillis());
		if(getMyAgent().getMonitored()==null)return;
		for(SLA sla : getMyAgent().getMonitored()){
			//System.out.println("genero dati casuali");
			//genero dati casuali:
			//richieste++ ogni tick
			//richieste soddisfatte = (100-SUCCESS_RATE)% di req ricevute
			//tempi di interarrivo random (0, 10000) msec
			//tempo ultima risposta random (0, 3000) msec
			if(getMyAgent().getMonitorData().containsKey(sla.toString())){
				MonitorData m = getMyAgent().getMonitorData().get(sla.toString());
				if(m.getReqRicevute()==null)m.setReqRicevute(0);
				if(m.getReqSoddisfatte()==null)m.setReqSoddisfatte(0);
				if(m.getTempoRispLast()==null)m.setTempoRispLast(random.nextInt(max));
				
				
				m.setReqRicevute(m.getReqRicevute()+1);
				m.getTempiInterarrivo().add(random.nextInt(50));
				///////////////////////////////////////
				//in teoria faccio dipendere sto tempo dal contesto
				Context old_context = context;
				setContext();
				max = refreshTempoRispLast(old_context,m);
			
				m.setTempoRispLast(random.nextInt(max));
				//System.out.println("Nuovo tempo di risposta"+m.getTempoRispLast());
				
				///////////////////////////////////////
				m.setConversationId(sla.toString());
				
				if(m.getReqRicevute()%SUCCESS_RATE!=0)
					m.setReqSoddisfatte(m.getReqSoddisfatte()+1);
				
				getMyAgent().getMonitorData().put(sla.toString(), m);
			}
		}

	}

	private Integer refreshTempoRispLast(Context old_context, MonitorData m) {
		//int TempoRispLast;
		
		double PercRamDisp = ((context.getRamDisp()-old_context.getRamDisp())/old_context.getRamDisp());
		double PercBandaDisp = ((context.getBandaDisp()-old_context.getBandaDisp())/old_context.getBandaDisp());;
		double PercCaricoCpu= old_context.getCaricoCpu()-context.getCaricoCpu();
		
		double PercCambMedio = (PercRamDisp+PercBandaDisp+PercCaricoCpu)/3;
		
		
		/*
		 * 
		 */
		int nuovoMax = (int)(max-(max*PercCambMedio));
		//System.out.print("RAMDISP"+PercRamDisp+"BandaDISP"+PercBandaDisp+"CPU"+PercCaricoCpu);
		//System.out.print("PercCambioMedio"+PercCambMedio);
		if(nuovoMax<=0)return 100;
		return nuovoMax;
		
	}

	private INodeMonitor getMyAgent(){
		return (INodeMonitor)myAgent;
	}
}
